/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ru.miit.elearning.hibernate.dao;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.hibernate.Session;
import ru.miit.elearning.hibernate.dto.Account;
import ru.miit.elearning.hibernate.dto.CurriculumLevel;
import ru.miit.elearning.hibernate.dto.UserData;
import ru.miit.elearning.hibernate.dto.UserIdentity;
import ru.miit.elearning.hibernate.dto.WorkItem;
import ru.miit.elearning.hibernate.dto.WorkItemId;

/**
 *
 * @author Cyclone
 */
public class CurriculumDAO extends GenericDAO {

    public CurriculumDAO(Session session) {
        super(session);
    }

    public void completeLab(int userId, int labId) {
        completeCurriculum(userId, labId);
    }

    public void cancelLab(int userId, int labId) {
        cancelCurriculum(userId, labId);
    }

    public void completeCourse(int userId, int courseId) {
        completeCurriculum(userId, courseId);
    }

    public void cancelCourse(int userId, int labId) {
        cancelCurriculum(userId, labId);
    }

    public void setMark(int studentId, int curriculumId, Integer tutorId, int mark) {
        WorkItem wi = findWorkItem(studentId, curriculumId);
        wi.setMark(mark == 0 ? null : mark);
        if (tutorId != null) {
            wi.setAccountByVerifier(new Account(tutorId));
        }

        session.saveOrUpdate(wi);
    }

    public boolean approveLab(int studentId, int courseId, int labNumber, Integer tutorId, boolean approve) {
        boolean completed = false;
        try {
            CurriculumLevel lab = (CurriculumLevel) session.createQuery("FROM CurriculumLevel "
                    + "WHERE curriculumLevel.id = :courseId "
                    + "AND numeral = :labNumber").setParameter("courseId", courseId).setParameter("labNumber", labNumber).uniqueResult();
            Integer labId = null;
            if (lab != null) {
                labId = lab.getId();

                WorkItem wi = (WorkItem) session.get(WorkItem.class, new WorkItemId(studentId, labId));
                if (wi != null) {
                    wi.setMark(approve ? 1 : null);

                    if (tutorId != null) {
                        Account tutorAccount = (Account) session.get(Account.class, tutorId);
                        wi.setAccountByVerifier(tutorAccount);
                    }

                    session.save(wi);
                    completed = true;
                }
            }
        } catch (Exception e) {
            Logger.getLogger(CurriculumDAO.class.getName()).log(Level.SEVERE, null, e);
            e.printStackTrace();
        }
        return completed;
    }

    private void completeCurriculum(int userId, int curriculumId) {
        WorkItem wi = findWorkItem(userId, curriculumId);

        wi.setFinish(Calendar.getInstance().getTime());
        wi.setActive(true);

        session.saveOrUpdate(wi);
    }

    private void cancelCurriculum(int userId, int curriculumId) {
        WorkItem wi = findWorkItem(userId, curriculumId);

        wi.setFinish(null);
        wi.setActive(false);

        session.saveOrUpdate(wi);
    }

    public List<UserData> findCoursesByStudentIdByTutor(int studentId, int tutorId) {
        //new UserData().getProfile().getProfileType().getId();
        return session.createQuery("from UserData ud "
                + "where ud.curriculumLevel.id in "
                + "(select ud2.curriculumLevel.id from UserData ud2 "
                + "where ud2.id.account = :tutorId "
                + "and ud2.profile.profileType.id = :tutorType) "
                + "and ud.id in "
                + "(select ud3.id from UserData ud3 "
                + "where ud3.id.account = :studentId "
                + "and ud3.profile.profileType.id = :studentType)").setParameter("tutorId", tutorId).setParameter("tutorType", PROFILE_TYPE_TUTOR).setParameter("studentId", studentId).setParameter("studentType", PROFILE_TYPE_STUDENT).list();
    }

    public List<UserData> findCoursesByStudentId(int userId) {
        return findCoursesByUserId(userId, PROFILE_TYPE_STUDENT);
    }

    public List<UserData> findCoursesByTutorId(int userId) {
        return findCoursesByUserId(userId, PROFILE_TYPE_TUTOR);
    }

    private List<UserData> findCoursesByUserId(int userId, short profileType) {
        return session.createQuery("from UserData ud where ud.id.account = :userId "
                + "and ud.profile.profileType.id = :profileType "
                + "and ud.curriculumLevel.curriculumLevelType.id = :curriculumLevelType "
                + "order by ud.curriculumLevel.title").setParameter("userId", userId).setParameter("profileType", profileType).setParameter("curriculumLevelType", CURRICULUM_LEVEL_TYPE_COURSE).list();
    }

    public String findCurriculumDescription(int curriculumLevelId) {
        //new CurriculumLevel().getId();
        String description =
                ((CurriculumLevel) session.createQuery("from CurriculumLevel cl "
                + "where cl.id = :curriculumLevelId").setParameter("curriculumLevelId", curriculumLevelId).uniqueResult()).getDescription();
        return description;

    }

    public WorkItem findWorkItem(int userId, int curriculumLevelId) {
        //return (WorkItem) session.createCriteria(WorkItem.class).add(Restrictions.eq("id.id", userId)).add(Restrictions.eq("id.task", curriculumLevelId)).uniqueResult();
        return (WorkItem) session.get(WorkItem.class, new WorkItemId(userId, curriculumLevelId));
    }
    /*
    public WorkItem findWorkItemByUserData(int userId, int curriculumLevelId) {
    //return (WorkItem) session.createCriteria(WorkItem.class).add(Restrictions.eq("id.id", userId)).add(Restrictions.eq("id.task", curriculumLevelId)).uniqueResult();
    return (WorkItem)session.get(WorkItem.class, new WorkItemId(userId, curriculumLevelId));
    }
     */

    public boolean isTutorSignedOnCourse(
            int userId, int curriculumLevelId) {

        UserData ud = (UserData) session.createQuery("from UserData ud where ud.id.account = :userId "
                + "and ud.id.curriculumLevel = :curriculumLevelId AND ud.id.profileType = :tutorType").setParameter("userId", userId).setParameter("curriculumLevelId", curriculumLevelId).setParameter("tutorType", PROFILE_TYPE_TUTOR).uniqueResult();
        return ud != null ? true : false;
    }

    /*
    public List<CurriculumLevel> findLabsByCourse(int courseId) {
    return session.createQuery("from CurriculumLevel cl " +
    "where cl.curriculumLevel.id = :courseId " +
    "and cl.curriculumLevelType.id = :labType " +
    "order by cl.numeral")
    .setParameter("courseId", courseId)
    .setParameter("labType", CURRICULUM_LEVEL_TYPE_LAB)
    .list();
    }
     */
    public List<WorkItem> findApproved(List<CurriculumLevel> curriculumList, List<UserIdentity> uiList) {
        List<WorkItem> approvedList = new ArrayList<WorkItem>();
        for (UserIdentity ui : uiList) {
            for (CurriculumLevel cl : curriculumList) {
                WorkItem wi = (WorkItem) session.get(WorkItem.class, new WorkItemId(ui.getAccount(), cl.getId()));
                if (wi != null && wi.getMark() != null && !wi.getMark().equals(0)) {
                    approvedList.add(wi);
                }
            }
        }
        return approvedList;
    }

    public String findLabDescription(int courseId, int labNumber) {
        String description = null;
        try {
            CurriculumLevel lab = (CurriculumLevel) session.createQuery("FROM CurriculumLevel WHERE curriculumLevel.id = :courseId "
                    + "AND numeral = :numeral").setParameter("courseId", courseId).setParameter("numeral", labNumber).uniqueResult();
            if (lab != null) {
                description = lab.getDescription();
            }
        } catch (Exception e) {
            Logger.getLogger(CurriculumDAO.class.getName()).log(Level.SEVERE, null, e);
            e.printStackTrace();
        }

        return description;
    }
}
